#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
# new Env("途虎养车")
# cron: 20 8 * * *
✦ 小程序信息    ▸ 名称：途虎养车I轮胎保养蓄电池洗车
▸ 类别：积分换实物
▸ 可换种类：只可换优惠券（目测无大用）
✦ 执行说明    ▸ 首次执行需手动进入小程序完成手机号绑定
▸ 每日自动执行签到任务
✦ 环境变量    ▸ Applet_TUHU_Wxid: 指定允许执行的账号(wxname或Wxid)，多个用英文逗号分隔
"""
import time
import json
import os
import requests
from typing import Optional, Tuple
from requests.exceptions import RequestException

class TuhuSignin:
    def __init__(self):
        self.base_url = "https://gateway.tuhu.cn"
        self.login_url = "https://cl-gateway.tuhu.cn"
        self.client = requests.Session()
        self.headers = {
            "host": "gateway.tuhu.cn",
            "authtype": "oauth",
            "user-agent": "Tuhu/7.29.0 (iPhone; iOS 18.3; Scale/3.0)",
            "accept-language": "zh-CN,zh-Hans;q=0.9",
            "accept": "*/*",
            "content-type": "application/json",
            "neederrorcode": "true",
            "accept-encoding": "gzip, deflate, br"
        }
        self.login_headers = {
            "Host": "cl-gateway.tuhu.cn",
            "Content-Type": "application/json",
            "Connection": "keep-alive",
            "channel": "wechat-miniprogram",
            "content-type": "application/json",
            "platformSource": "uni-app",
            "authType": "oauth",
            "currentPage": "pages/home/home",
            "api_level": "2",
            "Accept-Encoding": "gzip,compress,br,deflate",
            "User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 18_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/8.0.61(0x18003d2c) NetType/4G Language/zh_CN",
            "Referer": "https://servicewechat.com/wx27d20205249c56a3/1130/page-frame.html"
        }
        # 修复协议服务地址处理
        proxy = os.getenv("API_PROXY", "192.168.0.183:5000").replace("http://", "").replace("https://", "")
        self.local_proxy = f"http://{proxy}" if not proxy.startswith("http") else proxy
        self.app_id = "wx27d20205249c56a3"
        self.retry_times = 3  # 重试次数

    def _check_response(self, data: dict, operation: str) -> bool:
        code = data.get("code")
        if code == 10000:
            return True
        message = data.get("message", "未知错误")
        print(f"{operation}失败：{message}")
        return False

    def get_wx_list(self):
        """获取微信账户列表（带重试机制）"""
        url = f"{self.local_proxy}/getallwx"
        for i in range(self.retry_times):
            try:
                response = requests.get(url, timeout=10)
                if response.status_code == 200:
                    return response.json()
                print(f"获取微信列表失败(尝试 {i+1}/{self.retry_times}): HTTP {response.status_code}")
            except RequestException as e:
                print(f"获取微信列表失败(尝试 {i+1}/{self.retry_times}): {str(e)}")
            if i < self.retry_times - 1:
                time.sleep(2)
        return []

    def get_wx_code(self, wxid: str) -> Optional[str]:
        """获取小程序登录凭证（带重试机制）"""
        url = f"{self.local_proxy}/loginbyapp?Wxid={wxid}&appid={self.app_id}"
        for i in range(self.retry_times):
            try:
                response = requests.get(url, timeout=10)
                if response.status_code == 200:
                    return response.json().get("code")
                print(f"获取wxCode失败(尝试 {i+1}/{self.retry_times}): HTTP {response.status_code}")
            except RequestException as e:
                print(f"获取wxCode失败(尝试 {i+1}/{self.retry_times}): {str(e)}")
            if i < self.retry_times - 1:
                time.sleep(2)
        return None

    def login(self, wxid: str) -> Tuple[Optional[str], Optional[str]]:
        code = self.get_wx_code(wxid)
        if not code:
            print("获取微信登录code失败")
            return None, None

        url = f"{self.login_url}/cl-user-auth-login/login/authSilentSign"
        payload = {"channel": "WXAPP", "code": code}
        headers = self.login_headers.copy()
        
        for i in range(self.retry_times):
            try:
                response = self.client.post(
                    url,
                    json=payload,
                    headers=headers,
                    timeout=15
                )
                data = response.json()
                if self._check_response(data, "登录"):
                    result_data = data.get("data", {})
                    user_session = result_data.get("userSession")
                    nick_name = result_data.get("nickName", "微信用户")
                    if user_session:
                        print(f"账号{nick_name}登录成功")
                        return user_session, nick_name
                print(f"登录失败(尝试 {i+1}/{self.retry_times})")
            except Exception as e:
                print(f"登录请求失败(尝试 {i+1}/{self.retry_times}): {e}")
            if i < self.retry_times - 1:
                time.sleep(2)
        return None, None

    def check_signin_status(self, user_session: str) -> Optional[bool]:
        url = f"{self.base_url}/cl/cl-common-api/api/member/getSignInInfo"
        headers = self.headers.copy()
        headers["authorization"] = f"Bearer {user_session}"
        
        for i in range(self.retry_times):
            try:
                response = self.client.post(
                    url,
                    json={"channel": "app"},
                    headers=headers,
                    timeout=15
                )
                data = response.json()
                if self._check_response(data, "检查签到状态"):
                    return data.get("data", {}).get("signInStatus", False)
                print(f"检查签到状态失败(尝试 {i+1}/{self.retry_times})")
            except Exception as e:
                print(f"检查签到状态请求失败(尝试 {i+1}/{self.retry_times}): {e}")
            if i < self.retry_times - 1:
                time.sleep(2)
        return None

    def submit_signin(self, user_session: str) -> Optional[dict]:
        url = f"{self.base_url}/cl/cl-common-api/api/dailyCheckIn/userCheckIn"
        headers = self.headers.copy()
        headers["authorization"] = f"Bearer {user_session}"
        
        for i in range(self.retry_times):
            try:
                response = self.client.post(
                    url,
                    json={"channel": "app"},
                    headers=headers,
                    timeout=15
                )
                data = response.json()
                if self._check_response(data, "签到"):
                    result = data.get("data", {})
                    print(f"签到成功，获得{result.get('rewardIntegral', 0)}积分")
                    return result
                print(f"签到失败(尝试 {i+1}/{self.retry_times})")
            except Exception as e:
                print(f"签到请求失败(尝试 {i+1}/{self.retry_times}): {e}")
            if i < self.retry_times - 1:
                time.sleep(2)
        return None

    def get_current_integral(self, user_session: str) -> Optional[int]:
        url = f"{self.base_url}/cl/cl-common-api/api/member/getSignInInfo"
        headers = self.headers.copy()
        headers["authorization"] = f"Bearer {user_session}"
        
        for i in range(self.retry_times):
            try:
                response = self.client.post(
                    url,
                    json={"channel": "app"},
                    headers=headers,
                    timeout=15
                )
                data = response.json()
                if self._check_response(data, "获取积分"):
                    return data.get("data", {}).get("userIntegral", 0)
                print(f"获取积分失败(尝试 {i+1}/{self.retry_times})")
            except Exception as e:
                print(f"获取积分请求失败(尝试 {i+1}/{self.retry_times}): {e}")
            if i < self.retry_times - 1:
                time.sleep(2)
        return None

    def process_account(self, wx_account: dict) -> bool:
        wxid = wx_account.get("Wxid")
        wxname = wx_account.get("wxname", "未知用户")
        print(f"\n开始处理账号: {wxname} (Wxid: {wxid})")

        user_session, nick_name = self.login(wxid)
        if not user_session:
            print(f"账号 {wxname} 登录失败")
            return False

        sign_status = self.check_signin_status(user_session)
        if sign_status is None:
            print(f"账号 {wxname} 检查签到状态失败")
            return False

        if sign_status:
            integral = self.get_current_integral(user_session)
            if integral is not None:
                print(f"当前积分: {integral}")
        else:
            if self.submit_signin(user_session) is None:
                print(f"账号 {wxname} 签到失败")
                return False
            integral = self.get_current_integral(user_session)
            if integral is not None:
                print(f"当前积分: {integral}")
        return True

def main():
    print("="*50)
    print("途虎养车小程序签到 - 修复版")
    print("="*50)
    
    try:
        signin = TuhuSignin()
        print(f"使用协议服务地址: {signin.local_proxy}")
        
        # 获取允许的账号列表
        Applet_TUHU_Wxid = [x.strip() for x in os.getenv("Applet_TUHU_Wxid", "").split(",") if x.strip()]
        if Applet_TUHU_Wxid:
            print(f"允许的账号标识: {', '.join(Applet_TUHU_Wxid)}")
        else:
            print("未设置Applet_TUHU_Wxid，将处理所有账号")
        
        wx_accounts = signin.get_wx_list()
        if not wx_accounts:
            print("未获取到任何在线账号，请检查:")
            print("1. 协议服务是否正常运行")
            print(f"2. 访问 {signin.local_proxy}/getallwx 是否能返回数据")
            print("3. 网络连接是否正常")
            return

        print(f"获取到 {len(wx_accounts)} 个账号")
        
        # 过滤账号 - 同时支持 wxname 和 Wxid
        if Applet_TUHU_Wxid:
            filtered_accounts = [
                acc for acc in wx_accounts 
                if (acc.get("wxname", "") in Applet_TUHU_Wxid) or (acc.get("Wxid", "") in Applet_TUHU_Wxid)
            ]
            print(f"根据Applet_TUHU_Wxid过滤后，需要处理 {len(filtered_accounts)} 个账号")
        else:
            filtered_accounts = wx_accounts
            print("未设置Applet_TUHU_Wxid，处理所有账号")
        
        if not filtered_accounts:
            print("没有符合条件的账号需要处理")
            return
            
        for i, account in enumerate(filtered_accounts, 1):
            print(f"\n{'='*50}")
            print(f"处理第 {i}/{len(filtered_accounts)} 个账号: {account.get('wxname')} (Wxid: {account.get('Wxid')})")
            print(f"{'='*50}")
            try:
                signin.process_account(account)
            except Exception as e:
                print(f"处理账号时发生错误: {e}")
            
            if i < len(filtered_accounts):
                print("等待2秒...")
                time.sleep(2)
        
        print("\n所有账号处理完成")
    except Exception as e:
        print(f"脚本执行失败: {e}")
    finally:
        if 'signin' in locals():
            signin.client.close()

if __name__ == "__main__":
    main()